package com.markerhub.handler;

import com.alibaba.fastjson.JSON;
import com.markerhub.common.RedisKey;
import com.markerhub.common.lang.Result;
import com.markerhub.exception.apiException.authenticationException.TokenNullException;
import com.markerhub.exception.runtimeApiException.RedisNullValueException;
import com.markerhub.pojo.dto.Tb_UserDto;
import com.markerhub.pojo.dto.UserDto;
import com.markerhub.util.JWTUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


/**
 * @Author by MaXiaofeng
 * @Description 登录的拦截器，统一进行切面管理
 * @Date 2022/2/10 13:07
 * @Version 1.0.0
 */

/**
 * 拦截器的使用需要放入mvc配置中
 */
@Component
public class LoginHandler implements HandlerInterceptor {

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 在方法执行之前进行拦截
     *
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        /**
         * 1、判断请求是否是controller方法
         * 2、有些接口是不需要登录拦截，需要开发自定义注解 @NoAuth此注解不需要登录
         * 3、拿到token
         * 4、token认证 redis认证 =>user信息
         * 5、如果token认证通过则放行，认证不通过则返回未登录
         * 6、得到用户信息，放入ThreadLocal中
         */
        if (!(handler instanceof HandlerMethod)) {
            //如果访问的不是controller方法，则放行
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        if (handlerMethod.hasMethodAnnotation(Wx_Token_Auth.class) || handlerMethod.hasMethodAnnotation(Back_token_Auth.class)) {
            String token = request.getHeader("Authorization");
            if (token == null) {
                throw new TokenNullException();
            }
            token = token.replace("Bearer ", "");
            boolean verify = JWTUtils.verify(token);
            if (!verify) {
                response.setContentType("application/json;charset=utf-8");
                response.getWriter().write(JSON.toJSONString(Result.fail("未登录")));
                return false;
            }
            //从redis中取出token对应的账号信息
            String userJson = redisTemplate.opsForValue().get(RedisKey.TOKEN + token);
            if (userJson == null) {
                response.setContentType("application/json;charset=utf-8");
                response.getWriter().write(JSON.toJSONString(Result.fail("未登录")));
                return false;
            }
            if (handlerMethod.hasMethodAnnotation(Wx_Token_Auth.class)) {
                userJson = userJson.replace("\\", "");
                userJson = userJson.substring(1, userJson.length() - 1);
                UserDto userDto = JSON.parseObject(userJson, UserDto.class);
                //得到了用户信息放入ThreadLocal当中
                UserThreadLocal.remove();
                UserThreadLocal.put(userDto);
            } else if (handlerMethod.hasMethodAnnotation(Back_token_Auth.class)) {
                Tb_UserDto userDto = JSON.parseObject(userJson, Tb_UserDto.class);
                //得到了用户信息放入ThreadLocal当中
                Tb_UserThreadLocal.remove();
                Tb_UserThreadLocal.put(userDto);
            }
        }
        return true;
    }
}
